package com.jkm.config;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

/**
 * @Author: Zita
 * @Description: 配置Cache，继承CachingConfigurerSupport是为了重写keyGenerator()
 * @Date: Created in 2018/6/15
 */
@Configuration
public class RedisCacheConfig extends CachingConfigurerSupport {

    /**
     * 配置redisTemplate
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        Jackson2JsonRedisSerializer<Object> serializer = jackson2JsonRedisSerializer();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(serializer);
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(serializer);
        return redisTemplate;
    }

    /**
     * 使用redisTemplate配置CacheManager缓存管理器对象
     */
    @Bean
    public CacheManager cacheManager(RedisTemplate<String, Object> redisTemplate) {
        RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
        // 设置缓存默认过期时间
        cacheManager.setDefaultExpiration(60*60*24); // 3分钟
        cacheManager.setLoadRemoteCachesOnStartup(true);//// 启动时加载远程缓存
        cacheManager.setUsePrefix(true); // 使用前缀  即使用cacheNames属性
        // 设置cacheNames对应的过期时间
//        Map<String, Long> expiresMap = new HashMap<>();
//        expiresMap.put("test1", 100L);
//        expiresMap.put("test2", 500L);
//        cacheManager.setExpires(expiresMap);
        return cacheManager;
    }

    /**
     * 默认生成redis中的key的规则
     */
    @Override
    public KeyGenerator keyGenerator() {
        return (target, method, objects) -> {
            StringBuilder sb = new StringBuilder();
            sb.append(target.getClass().getName());
            sb.append(":");
            sb.append(method.getName());
            if (objects.length > 0) {
                sb.append(":");
                for (Object obj : objects) {
                    try {
                        String str = JSONObject.toJSONString(obj);
                        sb.append("," + obj.getClass().getName() + "->" + str);
                    } catch (Exception e) {
                        sb.append("," + obj.toString());
                    }
                }
            }
            return sb.toString();
        };
    }


    /**
     * 创建Jackson序列化转化器
     */
    private Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer() {
        final Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        final ObjectMapper objectMapper = Jackson2ObjectMapperBuilder
                .json().build();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
        return jackson2JsonRedisSerializer;
    }

}
